package com.demo.las.service;

import com.demo.las.entity.*;
import com.demo.las.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class StudyAccountingService {

    @Autowired
    private KnowledgeAssetRepository knowledgeAssetRepository;
    
    @Autowired
    private StudyRecordRepository studyRecordRepository;
    
    @Autowired
    private StudyPlanRepository studyPlanRepository;
    
    @Autowired
    private StudyAchievementRepository studyAchievementRepository;

    /**
     * 计算学习资产（资产负债表）
     */
    public BalanceSheet calculateBalanceSheet(Long userId) {
        BalanceSheet balanceSheet = new BalanceSheet();
        
        // 资产类
        balanceSheet.setTotalAssets(calculateTotalAssets(userId));
        balanceSheet.setCurrentAssets(calculateCurrentAssets(userId));
        balanceSheet.setFixedAssets(calculateFixedAssets(userId));
        balanceSheet.setIntangibleAssets(calculateIntangibleAssets(userId));
        
        // 负债类
        balanceSheet.setTotalLiabilities(calculateTotalLiabilities(userId));
        balanceSheet.setStudyDebts(calculateStudyDebts(userId));
        balanceSheet.setTimeLiabilities(calculateTimeLiabilities(userId));
        
        // 所有者权益
        balanceSheet.setOwnerEquity(balanceSheet.getTotalAssets().subtract(balanceSheet.getTotalLiabilities()));
        balanceSheet.setKnowledgeCapital(calculateKnowledgeCapital(userId));
        balanceSheet.setRetainedEarnings(calculateRetainedEarnings(userId));
        
        return balanceSheet;
    }

    /**
     * 计算损益表
     */
    public IncomeStatement calculateIncomeStatement(Long userId, LocalDate startDate, LocalDate endDate) {
        IncomeStatement incomeStatement = new IncomeStatement();
        
        // 学习收入
        incomeStatement.setStudyIncome(calculateStudyIncome(userId, startDate, endDate));
        incomeStatement.setAchievementIncome(calculateAchievementIncome(userId, startDate, endDate));
        incomeStatement.setTotalIncome(incomeStatement.getStudyIncome().add(incomeStatement.getAchievementIncome()));
        
        // 学习成本
        incomeStatement.setTimeCost(calculateTimeCost(userId, startDate, endDate));
        incomeStatement.setOpportunityCost(calculateOpportunityCost(userId, startDate, endDate));
        incomeStatement.setTotalCost(incomeStatement.getTimeCost().add(incomeStatement.getOpportunityCost()));
        
        // 净学习收益
        incomeStatement.setNetLearningProfit(incomeStatement.getTotalIncome().subtract(incomeStatement.getTotalCost()));
        
        // 效率指标
        incomeStatement.setEfficiencyRatio(calculateEfficiencyRatio(userId, startDate, endDate));
        incomeStatement.setRoiRatio(calculateROIRatio(userId, startDate, endDate));
        
        return incomeStatement;
    }

    /**
     * 计算现金流量表
     */
    public CashFlowStatement calculateCashFlowStatement(Long userId, LocalDate startDate, LocalDate endDate) {
        CashFlowStatement cashFlow = new CashFlowStatement();
        
        // 学习活动现金流
        cashFlow.setStudyActivitiesCashFlow(calculateStudyActivitiesCashFlow(userId, startDate, endDate));
        
        // 投资活动现金流（知识资产投入）
        cashFlow.setInvestmentActivitiesCashFlow(calculateInvestmentActivitiesCashFlow(userId, startDate, endDate));
        
        // 筹资活动现金流（学习计划投入）
        cashFlow.setFinancingActivitiesCashFlow(calculateFinancingActivitiesCashFlow(userId, startDate, endDate));
        
        // 净现金流
        cashFlow.setNetCashFlow(cashFlow.getStudyActivitiesCashFlow()
                .add(cashFlow.getInvestmentActivitiesCashFlow())
                .add(cashFlow.getFinancingActivitiesCashFlow()));
        
        return cashFlow;
    }

    /**
     * 生成学习财务报表
     */
    public Map<String, Object> generateLearningReport(Long userId, LocalDate startDate, LocalDate endDate) {
        Map<String, Object> report = new HashMap<>();
        
        report.put("资产负债表", calculateBalanceSheet(userId));
        report.put("损益表", calculateIncomeStatement(userId, startDate, endDate));
        report.put("现金流量表", calculateCashFlowStatement(userId, startDate, endDate));
        report.put("生成时间", LocalDate.now());
        report.put("报告期间", startDate + " 至 " + endDate);
        
        return report;
    }

    // 私有方法：计算各项指标

    private BigDecimal calculateTotalAssets(Long userId) {
        BigDecimal totalValue = knowledgeAssetRepository.getTotalCurrentValueByUser(userId);
        return totalValue != null ? totalValue : BigDecimal.ZERO;
    }

    private BigDecimal calculateCurrentAssets(Long userId) {
        // 流动资产：最近7天的学习时间价值
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(7);
        BigDecimal recentStudyTime = studyRecordRepository.getTotalStudyTimeByUserAndDateRange(userId, startDate, endDate);
        return recentStudyTime != null ? recentStudyTime.multiply(BigDecimal.valueOf(50)) : BigDecimal.ZERO;
    }

    private BigDecimal calculateFixedAssets(Long userId) {
        // 固定资产：掌握程度超过70%的知识资产
        List<KnowledgeAsset> fixedAssets = knowledgeAssetRepository.findByUserIdAndMasteryLevelGreaterThan(userId, BigDecimal.valueOf(70));
        return fixedAssets.stream()
                .map(asset -> asset.getCurrentValue() != null ? asset.getCurrentValue() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    private BigDecimal calculateIntangibleAssets(Long userId) {
        // 无形资产：成就价值
        BigDecimal achievementValue = studyAchievementRepository.getTotalAchievementValueByUser(userId);
        return achievementValue != null ? achievementValue : BigDecimal.ZERO;
    }

    private BigDecimal calculateTotalLiabilities(Long userId) {
        return calculateStudyDebts(userId).add(calculateTimeLiabilities(userId));
    }

    private BigDecimal calculateStudyDebts(Long userId) {
        // 学习债务：未完成的学习计划
        BigDecimal totalTarget = studyPlanRepository.getTotalTargetHoursByUser(userId);
        BigDecimal totalCompleted = studyPlanRepository.getTotalCompletedHoursByUser(userId);
        
        if (totalTarget == null || totalCompleted == null) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal uncompletedHours = totalTarget.subtract(totalCompleted);
        return uncompletedHours.compareTo(BigDecimal.ZERO) > 0 ? 
                uncompletedHours.multiply(BigDecimal.valueOf(30)) : BigDecimal.ZERO; // 每小时30元债务
    }

    private BigDecimal calculateTimeLiabilities(Long userId) {
        // 时间负债：逾期学习计划
        List<StudyPlan> overduePlans = studyPlanRepository.findOverduePlansByUser(userId);
        return overduePlans.stream()
                .map(plan -> {
                    BigDecimal targetHours = plan.getTargetHours() != null ? plan.getTargetHours() : BigDecimal.ZERO;
                    BigDecimal completedHours = plan.getCompletedHours() != null ? plan.getCompletedHours() : BigDecimal.ZERO;
                    return targetHours.subtract(completedHours);
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .multiply(BigDecimal.valueOf(50)); // 逾期每小时50元负债
    }

    private BigDecimal calculateKnowledgeCapital(Long userId) {
        // 知识资本：净学习成果
        BigDecimal totalAssets = calculateTotalAssets(userId);
        BigDecimal totalLiabilities = calculateTotalLiabilities(userId);
        return totalAssets.subtract(totalLiabilities);
    }

    private BigDecimal calculateRetainedEarnings(Long userId) {
        // 留存收益：长期积累的价值
        BigDecimal totalAchievementValue = studyAchievementRepository.getTotalAchievementValueByUser(userId);
        return totalAchievementValue != null ? totalAchievementValue.multiply(BigDecimal.valueOf(0.8)) : BigDecimal.ZERO;
    }

    private BigDecimal calculateStudyIncome(Long userId, LocalDate startDate, LocalDate endDate) {
        // 学习收入：有效学习时间价值
        BigDecimal totalStudyTime = studyRecordRepository.getTotalStudyTimeByUserAndDateRange(userId, startDate, endDate);
        BigDecimal avgEfficiency = studyRecordRepository.getAverageEfficiencyByUserAndDateRange(userId, startDate, endDate);
        
        if (totalStudyTime == null || avgEfficiency == null) {
            return BigDecimal.ZERO;
        }
        
        return totalStudyTime.multiply(avgEfficiency).multiply(BigDecimal.valueOf(60)); // 每小时60元收入
    }

    private BigDecimal calculateAchievementIncome(Long userId, LocalDate startDate, LocalDate endDate) {
        // 成就收入：期间获得的成就价值
        BigDecimal achievementValue = studyAchievementRepository.getTotalAchievementValueByUserAndDateRange(userId, startDate, endDate);
        return achievementValue != null ? achievementValue : BigDecimal.ZERO;
    }

    private BigDecimal calculateTimeCost(Long userId, LocalDate startDate, LocalDate endDate) {
        // 时间成本：学习时间的机会成本
        BigDecimal totalStudyTime = studyRecordRepository.getTotalStudyTimeByUserAndDateRange(userId, startDate, endDate);
        return totalStudyTime != null ? totalStudyTime.multiply(BigDecimal.valueOf(40)) : BigDecimal.ZERO; // 每小时40元成本
    }

    private BigDecimal calculateOpportunityCost(Long userId, LocalDate startDate, LocalDate endDate) {
        // 机会成本：未完成计划的机会成本
        return calculateStudyDebts(userId).multiply(BigDecimal.valueOf(0.1));
    }

    private BigDecimal calculateEfficiencyRatio(Long userId, LocalDate startDate, LocalDate endDate) {
        // 效率比率：有效学习时间 / 总学习时间
        BigDecimal totalStudyTime = studyRecordRepository.getTotalStudyTimeByUserAndDateRange(userId, startDate, endDate);
        BigDecimal avgEfficiency = studyRecordRepository.getAverageEfficiencyByUserAndDateRange(userId, startDate, endDate);
        
        if (totalStudyTime == null || avgEfficiency == null || totalStudyTime.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal effectiveTime = totalStudyTime.multiply(avgEfficiency);
        return effectiveTime.divide(totalStudyTime, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
    }

    private BigDecimal calculateROIRatio(Long userId, LocalDate startDate, LocalDate endDate) {
        // 投资回报率：(学习收入 - 时间成本) / 时间成本
        BigDecimal studyIncome = calculateStudyIncome(userId, startDate, endDate);
        BigDecimal timeCost = calculateTimeCost(userId, startDate, endDate);
        
        if (timeCost.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal profit = studyIncome.subtract(timeCost);
        return profit.divide(timeCost, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
    }

    private BigDecimal calculateStudyActivitiesCashFlow(Long userId, LocalDate startDate, LocalDate endDate) {
        // 学习活动现金流：学习收入 - 时间成本
        return calculateStudyIncome(userId, startDate, endDate).subtract(calculateTimeCost(userId, startDate, endDate));
    }

    private BigDecimal calculateInvestmentActivitiesCashFlow(Long userId, LocalDate startDate, LocalDate endDate) {
        // 投资活动现金流：知识资产投入（负数）
        BigDecimal totalStudyTime = studyRecordRepository.getTotalStudyTimeByUserAndDateRange(userId, startDate, endDate);
        return totalStudyTime != null ? totalStudyTime.multiply(BigDecimal.valueOf(-30)) : BigDecimal.ZERO;
    }

    private BigDecimal calculateFinancingActivitiesCashFlow(Long userId, LocalDate startDate, LocalDate endDate) {
        // 筹资活动现金流：学习计划投入（负数）
        return BigDecimal.valueOf(-500); // 每月固定学习计划投入500元
    }

    // 内部类：财务报表结构
    public static class BalanceSheet {
        private BigDecimal totalAssets = BigDecimal.ZERO;
        private BigDecimal currentAssets = BigDecimal.ZERO;
        private BigDecimal fixedAssets = BigDecimal.ZERO;
        private BigDecimal intangibleAssets = BigDecimal.ZERO;
        private BigDecimal totalLiabilities = BigDecimal.ZERO;
        private BigDecimal studyDebts = BigDecimal.ZERO;
        private BigDecimal timeLiabilities = BigDecimal.ZERO;
        private BigDecimal ownerEquity = BigDecimal.ZERO;
        private BigDecimal knowledgeCapital = BigDecimal.ZERO;
        private BigDecimal retainedEarnings = BigDecimal.ZERO;

        // Getters and Setters
        public BigDecimal getTotalAssets() { return totalAssets; }
        public void setTotalAssets(BigDecimal totalAssets) { this.totalAssets = totalAssets; }
        
        public BigDecimal getCurrentAssets() { return currentAssets; }
        public void setCurrentAssets(BigDecimal currentAssets) { this.currentAssets = currentAssets; }
        
        public BigDecimal getFixedAssets() { return fixedAssets; }
        public void setFixedAssets(BigDecimal fixedAssets) { this.fixedAssets = fixedAssets; }
        
        public BigDecimal getIntangibleAssets() { return intangibleAssets; }
        public void setIntangibleAssets(BigDecimal intangibleAssets) { this.intangibleAssets = intangibleAssets; }
        
        public BigDecimal getTotalLiabilities() { return totalLiabilities; }
        public void setTotalLiabilities(BigDecimal totalLiabilities) { this.totalLiabilities = totalLiabilities; }
        
        public BigDecimal getStudyDebts() { return studyDebts; }
        public void setStudyDebts(BigDecimal studyDebts) { this.studyDebts = studyDebts; }
        
        public BigDecimal getTimeLiabilities() { return timeLiabilities; }
        public void setTimeLiabilities(BigDecimal timeLiabilities) { this.timeLiabilities = timeLiabilities; }
        
        public BigDecimal getOwnerEquity() { return ownerEquity; }
        public void setOwnerEquity(BigDecimal ownerEquity) { this.ownerEquity = ownerEquity; }
        
        public BigDecimal getKnowledgeCapital() { return knowledgeCapital; }
        public void setKnowledgeCapital(BigDecimal knowledgeCapital) { this.knowledgeCapital = knowledgeCapital; }
        
        public BigDecimal getRetainedEarnings() { return retainedEarnings; }
        public void setRetainedEarnings(BigDecimal retainedEarnings) { this.retainedEarnings = retainedEarnings; }
    }

    public static class IncomeStatement {
        private BigDecimal studyIncome = BigDecimal.ZERO;
        private BigDecimal achievementIncome = BigDecimal.ZERO;
        private BigDecimal totalIncome = BigDecimal.ZERO;
        private BigDecimal timeCost = BigDecimal.ZERO;
        private BigDecimal opportunityCost = BigDecimal.ZERO;
        private BigDecimal totalCost = BigDecimal.ZERO;
        private BigDecimal netLearningProfit = BigDecimal.ZERO;
        private BigDecimal efficiencyRatio = BigDecimal.ZERO;
        private BigDecimal roiRatio = BigDecimal.ZERO;

        // Getters and Setters
        public BigDecimal getStudyIncome() { return studyIncome; }
        public void setStudyIncome(BigDecimal studyIncome) { this.studyIncome = studyIncome; }
        
        public BigDecimal getAchievementIncome() { return achievementIncome; }
        public void setAchievementIncome(BigDecimal achievementIncome) { this.achievementIncome = achievementIncome; }
        
        public BigDecimal getTotalIncome() { return totalIncome; }
        public void setTotalIncome(BigDecimal totalIncome) { this.totalIncome = totalIncome; }
        
        public BigDecimal getTimeCost() { return timeCost; }
        public void setTimeCost(BigDecimal timeCost) { this.timeCost = timeCost; }
        
        public BigDecimal getOpportunityCost() { return opportunityCost; }
        public void setOpportunityCost(BigDecimal opportunityCost) { this.opportunityCost = opportunityCost; }
        
        public BigDecimal getTotalCost() { return totalCost; }
        public void setTotalCost(BigDecimal totalCost) { this.totalCost = totalCost; }
        
        public BigDecimal getNetLearningProfit() { return netLearningProfit; }
        public void setNetLearningProfit(BigDecimal netLearningProfit) { this.netLearningProfit = netLearningProfit; }
        
        public BigDecimal getEfficiencyRatio() { return efficiencyRatio; }
        public void setEfficiencyRatio(BigDecimal efficiencyRatio) { this.efficiencyRatio = efficiencyRatio; }
        
        public BigDecimal getRoiRatio() { return roiRatio; }
        public void setRoiRatio(BigDecimal roiRatio) { this.roiRatio = roiRatio; }
    }

    public static class CashFlowStatement {
        private BigDecimal studyActivitiesCashFlow = BigDecimal.ZERO;
        private BigDecimal investmentActivitiesCashFlow = BigDecimal.ZERO;
        private BigDecimal financingActivitiesCashFlow = BigDecimal.ZERO;
        private BigDecimal netCashFlow = BigDecimal.ZERO;

        // Getters and Setters
        public BigDecimal getStudyActivitiesCashFlow() { return studyActivitiesCashFlow; }
        public void setStudyActivitiesCashFlow(BigDecimal studyActivitiesCashFlow) { this.studyActivitiesCashFlow = studyActivitiesCashFlow; }
        
        public BigDecimal getInvestmentActivitiesCashFlow() { return investmentActivitiesCashFlow; }
        public void setInvestmentActivitiesCashFlow(BigDecimal investmentActivitiesCashFlow) { this.investmentActivitiesCashFlow = investmentActivitiesCashFlow; }
        
        public BigDecimal getFinancingActivitiesCashFlow() { return financingActivitiesCashFlow; }
        public void setFinancingActivitiesCashFlow(BigDecimal financingActivitiesCashFlow) { this.financingActivitiesCashFlow = financingActivitiesCashFlow; }
        
        public BigDecimal getNetCashFlow() { return netCashFlow; }
        public void setNetCashFlow(BigDecimal netCashFlow) { this.netCashFlow = netCashFlow; }
    }
}
